#ifndef _CKBLOCKINGQUEUE_H_
#define _CKBLOCKINGQUEUE_H_



#include <mutex>
#include <condition_variable>
#include <queue>
#include <string>

namespace K_Engine
{
	/**
	 * A simple blocking queue class with template
	 * @Author : Kai.Leung
	 * @Date   : 2016-3-28
	 */
	template<typename T>
	class CKBlockingQueue
	{
	private:
		std::queue<T> m_queue;
		std::mutex m_mutex;
		std::condition_variable m_condition;
		
	public:
		CKBlockingQueue() {  }
		~CKBlockingQueue() {  }
		
		/**
		 * Push something T in queue
		 * @Author : Kai.Leung
		 * @Date   : 2016-3-28
		 * @params : template T
		 */
		void Push(T push)
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			m_queue.push(push);
			m_condition.notify_all();
		}
		
		/**
		 * Pop template T in queue
		 * @Author : Kai.Leung
		 * @Date   : 2016-3-28
		 * @return : template T
		 */
		T Pop()
		{
			std::unique_lock<std::mutex> lock(m_mutex);
			m_condition.wait(lock, [this]{return !m_queue.empty();});
			T var = m_queue.front();
			m_queue.pop();
			return var;
		}
		
		/**
		 * Return the blocking in queue pop
		 * @Author : Kai.Leung
		 * @Date   : 2016-3-28
		 */
		void JustReturnWait()
		{
			m_condition.notify_all();
		}
		
		/**
		 * Get the size of queue
		 * @Author : Kai.Leung
		 * @Date   : 2016-3-28
		 * @return : size of queue
		 */
		int Size()
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			return m_queue.size();
		}
		
		
		/**
		 * Clean the menber form queue
		 * @Author : Kai.Leung
		 * @Date   : 2016-3-28
		 * @return : size of queue
		 */
		void Clear()
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			int size = m_queue.size();
			for(int i =0; i < size; i++)
			{
				m_queue.pop();
			}
		}
	};
}

#endif // ! _CKBLOCKINGQUEUE_H_